package com.nuumoblie.bluetoothtools.ble.db.repository;

import android.app.Application;
import android.database.Cursor;
import android.os.AsyncTask;
import android.util.Log;

import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;

import com.nuumoblie.bluetoothtools.AppApplication;
import com.nuumoblie.bluetoothtools.ble.db.AdvertiseDatabase;
import com.nuumoblie.bluetoothtools.ble.db.dao.BleProductDao;
import com.nuumoblie.bluetoothtools.ble.db.dao.OnLoadComplete;
import com.nuumoblie.bluetoothtools.ble.db.entity.BleAdvertiseInfo;
import com.nuumoblie.bluetoothtools.ble.db.entity.BleCharacteristicEntity;
import com.nuumoblie.bluetoothtools.ble.db.entity.BleDescriptorEntity;
import com.nuumoblie.bluetoothtools.ble.db.entity.BleProductTypeEntity;
import com.nuumoblie.bluetoothtools.ble.db.entity.BleServiceEntity;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class AdvertiseConfigRepository {

    private BleProductDao mProductDao;
    private LiveData<List<BleProductTypeEntity>> mAllProducts;
    private List<BleAdvertiseInfo> mAdvertiseInfos;
    private ObtainAsyncTask mObtainAsyncTask;

    // Note that in order to unit test the WordRepository, you have to remove the Application
    // dependency. This adds complexity and much more code, and this sample is not about testing.
    // See the BasicSample in the android-architecture-components repository at
    // https://github.com/googlesamples
    public AdvertiseConfigRepository(Application application) {
        Log.v("lmjssjj", "AdvertiseConfigRepository");
        AdvertiseDatabase db = AdvertiseDatabase.getInstance(application);
        Cursor c = db.query("select * from simulate_product_type", null);
        Log.v("lmjssjj", "count:" + c.getCount());
        mProductDao = db.getProductDao();
        mAllProducts = mProductDao.getAllProducts();
    }

    // Room executes all queries on a separate thread.
    // Observed LiveData will notify the observer when the data has changed.
    public LiveData<List<BleProductTypeEntity>> getAllProducts() {
        return mAllProducts;
    }
//    public LiveData<List<BleProductTypeEntity>> getAllProducts() {
//        return mAllProducts;
//    }

    public void getAdvertiseInfos(OnLoadComplete onLoadComplete) {
        if (mAdvertiseInfos != null) {
            onLoadComplete.onComplete(mAdvertiseInfos);
        } else {
            if (mObtainAsyncTask != null)
                mObtainAsyncTask.cancel(true);
            mObtainAsyncTask = new ObtainAsyncTask(onLoadComplete);
            mObtainAsyncTask.execute();
        }
    }

    // You must call this on a non-UI thread or your app will crash.
    // Like this, Room ensures that you're not doing any long running operations on the main
    // thread, blocking the UI.
    public void insert(BleProductTypeEntity entity) {
        new insertAsyncTask(mProductDao).execute(entity);
    }

    private static class insertAsyncTask extends AsyncTask<BleProductTypeEntity, Void, Void> {

        private BleProductDao mAsyncTaskDao;

        insertAsyncTask(BleProductDao dao) {
            mAsyncTaskDao = dao;
        }

        @Override
        protected Void doInBackground(final BleProductTypeEntity... params) {
            mAsyncTaskDao.insert(params[0]);
            return null;
        }
    }

    private class ObtainAsyncTask extends AsyncTask<Void, Void, List<BleAdvertiseInfo>> {

        OnLoadComplete mOnLoadComplete;

        ObtainAsyncTask(OnLoadComplete onLoadComplete) {
            this.mOnLoadComplete = onLoadComplete;
        }

        @Override
        protected List<BleAdvertiseInfo> doInBackground(Void... voids) {

            List<BleAdvertiseInfo> advertiseInfos = new ArrayList<>();
            BleAdvertiseInfo info = null;
            List<BleProductTypeEntity> products = AdvertiseDatabase.getInstance(AppApplication.getInstance()).getProductDao().getAllProductType();
            if (null != products && products.size() > 0) {
                for (BleProductTypeEntity entity : products) {
                    info = new BleAdvertiseInfo();
                    List<BleServiceEntity> serviceEntities = AdvertiseDatabase
                            .getInstance(AppApplication.getInstance())
                            .getServiceDao()
                            .getServices(entity.get_id());
                    info.setBleProduct(entity);

                    if (null != serviceEntities && serviceEntities.size() > 0) {
                        List<BleAdvertiseInfo.ServiceInfo> serviceInfos = new ArrayList<>();
                        BleAdvertiseInfo.ServiceInfo serviceInfo = null;

                        for (BleServiceEntity serviceEntity : serviceEntities) {
                            List<BleCharacteristicEntity> characteristicEntities = AdvertiseDatabase.getInstance(AppApplication.getInstance())
                                    .getCharacteristicDao()
                                    .getCharacteristic(serviceEntity.get_id());
                            serviceInfo = new BleAdvertiseInfo.ServiceInfo();
                            serviceInfo.setService(serviceEntity);


                            if (null != characteristicEntities && characteristicEntities.size() > 0) {
                                List<BleAdvertiseInfo.CharacteristicInfo> characteristicInfos = new ArrayList<>();
                                BleAdvertiseInfo.CharacteristicInfo characteristicInfo = null;

                                for (BleCharacteristicEntity characteristicEntity : characteristicEntities) {
                                    characteristicInfo = new BleAdvertiseInfo.CharacteristicInfo();
                                    List<BleDescriptorEntity> descriptorEntities = AdvertiseDatabase.getInstance(AppApplication.getInstance())
                                            .getDescriptorDao()
                                            .getDescriptors(characteristicEntity.get_id());
                                    characteristicInfo.setCharacteristic(characteristicEntity);


                                    if (null != descriptorEntities && descriptorEntities.size() > 0) {
                                        List<BleAdvertiseInfo.DescriptorInfo> descriptorInfos = new ArrayList<>();
                                        BleAdvertiseInfo.DescriptorInfo descriptorInfo = null;
                                        for (BleDescriptorEntity descriptorEntity : descriptorEntities) {
                                            descriptorInfo = new BleAdvertiseInfo.DescriptorInfo();
                                            descriptorInfo.setDescristor(descriptorEntity);
                                            descriptorInfos.add(descriptorInfo);
                                        }
                                        characteristicInfo.setDescriptorInfos(descriptorInfos);
                                    }
                                    characteristicInfos.add(characteristicInfo);
                                }
                                serviceInfo.setCharacteristicInfos(characteristicInfos);

                            }
                            serviceInfos.add(serviceInfo);
                        }

                        info.setServiceInfos(serviceInfos);
                    }
                    advertiseInfos.add(info);
                }
            }

            return advertiseInfos;
        }


        @Override
        protected void onPostExecute(List<BleAdvertiseInfo> bleAdvertiseInfos) {
            if (null != mOnLoadComplete) {
                mOnLoadComplete.onComplete(bleAdvertiseInfos);
            }
            mAdvertiseInfos = bleAdvertiseInfos;
        }
    }

}
